package gamebackend;

import framework.Color;
import framework.GraphicsWrapper;

/**
 * A giant beam of energy which strikes through the stage after a short warning.
 * 
 * @author Jonathan Caddey
 */
/**
 * @author Caddey
 *
 */
public class EnviroLaser implements Hazard {
//	private static final Color INNER_COLOR = new Color(240, 210, 225);
//	private static final Color FRINGE_COLOR = new Color(230, 150, 210);
//	private static final Color INNER_COLOR = new Color(225, 180, 190);
//	private static final Color FRINGE_COLOR = new Color(240, 10, 15);
	private static final Color INNER_COLOR = new Color(255, 255, 255, 150);//Color(205, 180, 225);
	private static final Color FRINGE_COLOR = new Color(210, 80, 250);//Color(190, 115, 225);
	private static final Color WAKE_COLOR = new Color(245, 255, 235);
	private static final int BUILD_UP_DURATION = 1050;//950;
	private static final int LASER_DURATION = 700;//900;
	private static final int WAKE_DURATION = 400;//400;
	private static final double INNER_WIDTH_RATIO = .7;
	private final double my_x;
	
	/**
	 * The bottom of the danger length.
	 */
	final double my_fireY;
	private double my_width = 100;
	private final double my_height;
	private final double my_dangerLength;
	private final double my_warningLength;
	
	/**
	 * The laser fades out after its destruction.
	 */
	private final double my_wakeLength;

	/**
	 * The original distance the laser must travel before hitting the player.
	 */
	private final double my_travelDistance;
	
	/**
	 * Distance before the laser fires, decreasing until the laser fires at 0. 
	 */
	private double my_y;
	private double my_fixedY;
	
	/**
	 * Create a laser that fires after a delay.  The laser can be imagined as consisting
	 * of three rectangular parts--a warning length, danger length, and wake length.
	 * As the ship moves through the warning length a visual indicator warns the player of
	 * the dimensions of the laser.  The danger length is where the laser actually is firing
	 * and will damage the player.  The wake length is where the glow of the laser fades,
	 * but the laser does not do damage.
	 * @param the_left the left edge of the laser.
	 * @param the_right the right edge of the laser.
	 * @param the_fireY the bottom y coordinate of the danger zone where the laser starts firing.
	 * @param the_height the vertical height of the laser.
	 * @param the_distanceBeforeFire how far above the_fireY the laser starts.
	 * @param the_destructionShipYVelocity the velocity of the hypothetical ship used for determining
	 * the destruction length.
	 * @param the_warningShipYVelocity the velocity of the player's ship used for determining the warning
	 * length and wake length.
	 */
	public EnviroLaser(final double the_left, final double the_right, final double the_fireY,
			final double the_height, final double the_distanceBeforeFire,
			final double the_destructionShipYVelocity, final double the_warningShipYVelocity) {
		my_height = the_height;
		my_x = (the_right + the_left) / 2;
		my_width = (the_right - my_x) * 2;
		my_dangerLength = LASER_DURATION * the_destructionShipYVelocity;
		my_warningLength = Math.min(BUILD_UP_DURATION * the_warningShipYVelocity,
				the_distanceBeforeFire);
		my_wakeLength = WAKE_DURATION * the_warningShipYVelocity;
		my_fireY = the_fireY;
		my_y = the_distanceBeforeFire;
		my_fixedY = my_y;
		my_travelDistance = the_distanceBeforeFire;
	}
	@Override
	public void step(final double the_yChange) {
		my_y -= the_yChange;
	}
	@Override
	public void fixedStep(final double the_yChange) {
		my_fixedY -= the_yChange;
	}

	@Override
	public void render(GraphicsWrapper g) {
		/*Debug
		g.setColor(new Color(255, 0, 0, 128));
		g.fillRect((int) (my_x - my_width / 2), (int)(my_height - my_fixedY - my_fireY - my_dangerLength), (int)my_width, (int) my_dangerLength);
		//*/
		g.setColor(FRINGE_COLOR);

		if (my_y > 0 && my_y < my_warningLength) {
			// Warning
			final double ratio = Math.min(1, (my_warningLength - my_y) / (my_warningLength * .9));
			final double offset = my_width / 2 - (double) my_width / 2 * ratio;
			g.setColor(FRINGE_COLOR);
			final int width = (int) (my_width / 7 * ratio);
			g.fillRect((int)(my_x - offset - width / 2), 0, width, (int) my_height);
			g.fillRect((int)(my_x + offset - width / 2), 0, width, (int) my_height);
		}
		if (isDangerous()) {
			g.setColor(FRINGE_COLOR);
			g.fillRect((int)(getLeft()), 0, (int)my_width, (int) my_height);
			g.setColor(INNER_COLOR);
			final double innerWidth  = my_width * (INNER_WIDTH_RATIO + (1 - INNER_WIDTH_RATIO) * (-my_y) / my_dangerLength);
			g.fillRect((int)(my_x - innerWidth / 2), 0, (int) innerWidth, (int) my_height);
		}
		if (my_y < -my_dangerLength) {
			// Wake length
			final double ratio = -my_y / (my_dangerLength + my_wakeLength);
			final int alpha = 255 - (int) (255 * ratio * ratio);
			g.setColor(new Color(WAKE_COLOR.getRed(),
					WAKE_COLOR.getGreen(),
					WAKE_COLOR.getBlue(),
					alpha));
			g.fillRect((int)(getLeft()), 0, (int)my_width, (int) my_height);
		}
		
		
	}
	public double getLeft() {
		return my_x - my_width / 2;
	}
	public double getTop() {
		return 0;
	}
	public double getWidth() {
		return my_width;
	}
	public double getHeight() {
		return my_height;
	}
	
	/**
	 * @return whether the laser is actually firing.
	 */
	public boolean isDangerous() {
		return my_y < 0 && my_y >= - my_dangerLength;
	}
	
	
	
	/**
	 * The area where the player can hit the laser
	 * is a danger zone.  Its length is
	 * the duration of the laser multiplied by the
	 * speed of the flier.
	 * @return how tall of an area the laser
	 * forms where the player would be hit by the laser.
	 */
	public double getDangerLength() {
		return my_dangerLength;
	}
	/**
	 * @return how high blocks are destroyed.
	 */
	public double getDestructionLength() {
		return my_height - my_fireY + my_dangerLength;
	}
	public double getTravelled() {
		return my_travelDistance - my_y;
	}

	@Override
	public boolean isAlive() {
		return my_y > -my_dangerLength - my_wakeLength;
	}
	@Override
	public double getRemaining() {
		return getDangerLength() - (my_travelDistance - my_fixedY);
	}

}
